﻿using Sunny.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace SmartMotion.Core.Tools
{
    public partial class FrmSelectField : UIForm
    {
        #region 字段
            
        private readonly FieldBase _field;
       
        private List<Type> _typeList;

        //private List<MethodInfo> _propertyList;
        private readonly List<string> _dllList;

        //private readonly List<Type> _allType;
        private readonly List<Type> _searchType;

        private List<FieldInfo> _propertyList;
        private List<FieldInfo> _searchPropertyList;
        #endregion 字段

        public FrmSelectField(FieldBase field)

        {
            _field = field;
            _typeList = new List<Type>();
            _dllList = new List<string>();
            //_allType = new List<Type>();
            _searchType = new List<Type>();
            _propertyList = new List<FieldInfo>();
            _searchPropertyList = new List<FieldInfo>();
            InitializeComponent();
        }

        private void FrmGetProperty_Load(object sender, EventArgs e)
        {
            RefreshDll();
        }

        //刷新DLL，加载上一次的配置
        private void RefreshDll()
        {
            var files = Directory.GetFiles(Environment.CurrentDirectory, "*.dll");
            lstDll.Items.Clear();
            foreach (var file in files)
            {
                try
                {
                    Assembly curDll = Assembly.LoadFile(file);
                    var types = curDll.GetTypes();

                    if (types.Length > 0)
                    {
                        lstDll.Items.Add(Path.GetFileName(file));
                        _dllList.Add(Path.GetFileName(file));
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception);
                }
            }

            #region 加载上一次的配置

            int index = lstDll.Items.IndexOf(_field.Dll);
            lstDll.SelectedIndex = index;

            foreach (var type in _typeList)
            {
                if (type.FullName == _field.TypeName)
                {
                    lstType.SelectedItem = type;
                    break;
                }
            }

            foreach (var methodInfo in _propertyList)
            {
                if (methodInfo.Name == _field.MethodName)
                {
                    //if (methodInfo.GetParameters().Length == _field.ParaTypes.Count)
                    {
                        lstProperty.SelectedItem = methodInfo;
                        break;
                    }
                }
            }
            txtName.Text = _field.ItemName;

            #endregion 加载上一次的配置
        }

        private void lstDll_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstDll.SelectedItem == null) return;
            string fileName = Environment.CurrentDirectory + "\\" + lstDll.SelectedItem;
            Assembly curDll = Assembly.LoadFile(fileName);
            _typeList = curDll.GetTypes().ToList();
            BindingSource bs = new BindingSource();
            bs.DataSource = _typeList;
            lstType.DataSource = bs;
            lstType.DisplayMember = "Name";
        }

        private void txtSearchDll_TextChanged(object sender, EventArgs e)
        {
            lstDll.Items.Clear();
            string txtSearch = txtSearchDll.Text;
            foreach (var dll in _dllList.Where(dll => dll.ToLower().Contains(txtSearch.ToLower())))
            {
                lstDll.Items.Add(dll);
            }
        }

        private void txtSearchType_TextChanged(object sender, EventArgs e)
        {
            string txtSearch = txtSearchType.Text;
            _searchType.Clear();
            foreach (var type in _typeList.Where(type => type.Name.ToLower().Contains(txtSearch)))
            {
                _searchType.Add(type);
            }
            var bs = new BindingSource();
            bs.DataSource = _searchType;
            lstType.DataSource = bs;
            lstType.DisplayMember = "Name";
        }

        private void lstType_SelectedIndexChanged(object sender, EventArgs e)
        {
            var type = lstType.SelectedItem as Type;
            if (type == null) return;
            _propertyList = type.GetFields().ToList();
            _searchPropertyList = type.GetFields().ToList();
            var bs = new BindingSource();
            bs.DataSource = _searchPropertyList;
            lstProperty.DataSource = bs;
            lstProperty.DisplayMember = "signature";
        }

        private void txtSearchMethod_TextChanged(object sender, EventArgs e)
        {
            string txtSearch = txtSearchMethod.Text;
            _searchPropertyList.Clear();
            foreach (var methodInfo in _propertyList)
            {
                if (methodInfo.Name.ToLower().Contains(txtSearch))
                {
                    _searchPropertyList.Add(methodInfo);
                }
            }
            var bs = new BindingSource();
            bs.DataSource = _searchPropertyList;
            lstProperty.DataSource = bs;
            lstProperty.DisplayMember = "signature";
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (txtName.Text.Length == 0)
            {
                ShowErrorDialog("请输入一个名称");
                return;
            }

            _field.ItemName = txtName.Text;
            _field.Dll = lstDll.SelectedItem.ToString();
            _field.TypeName = (lstType.SelectedItem as Type)?.FullName;
            FieldInfo fieldInfo = lstProperty.SelectedItem as FieldInfo;
            if (fieldInfo == null)
            {
                ShowErrorDialog("请选择一个属性");
                return;
            }
            _field.MethodName = fieldInfo.Name;
            _field.IsStatic = false;
            _field.Parms.Clear();
            _field.ParaTypes.Clear();
            _field.ParaNames.Clear();
            if (_field is GetField)
            {
                _field.ReturnType = fieldInfo.FieldType.FullName;
            }
            else
            {
                _field.ReturnType = "Void";
                _field.ParaTypes.Add(fieldInfo.FieldType.FullName);
                _field.ParaNames.Add(fieldInfo.Name);
                _field.Parms.Add(new MethodParms() { Name = fieldInfo.Name, Type = fieldInfo.FieldType.FullName, VarSelected = false });
            }
            DialogResult = DialogResult.OK;
            Close();
        }

        private void lstProperty_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstProperty.SelectedItem is FieldInfo pi) txtName.Text = pi.Name;
        }
    }
}
